﻿using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.UI;
using Microsoft.EntityFrameworkCore;
using Partner.Surround.Authorization;
using Partner.Surround.Base.DataDictionaries.Dto;
using Partner.Surround.Notifications;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Partner.Surround.Base.DataDictionaries
{
    public class DataDictionaryAppService : SurroundAppServiceBase, IDataDictionaryAppService
    {
        #region 初始化
        private readonly IRepository<DataDictionary, long> _dataDictionaryRepository;
        private readonly IRepository<DataDictionaryItem, long> _dataDictionaryItemRepository;
        private readonly IAppNotifier _appNotifier;

        public DataDictionaryAppService(
            IRepository<DataDictionary, long> dataDictionaryRepository,
            IRepository<DataDictionaryItem, long> dataDictionaryItemRepository,
            IAppNotifier appNotifier)
        {
            _dataDictionaryRepository = dataDictionaryRepository;
            _dataDictionaryItemRepository = dataDictionaryItemRepository;
            _appNotifier = appNotifier;
        }
        #endregion

        #region 数据字典
        public async Task<ListResultDto<DataDictionaryListDto>> GetAllDataDictionary()
        {
            var items = await _dataDictionaryRepository.GetAllListAsync();
            return new ListResultDto<DataDictionaryListDto>(ObjectMapper.Map<List<DataDictionaryListDto>>(items));
        }

        public async Task<GetDataDictionaryForEditOutput> GetDataDictionaryForEdit(NullableIdDto<long> input)
        {
            var dataDictionaryEditDto = new DataDictionaryEditDto();
            if (input.Id.HasValue)
            {
                var dataDictionary = await _dataDictionaryRepository.GetAsync(input.Id.Value);
                dataDictionaryEditDto = ObjectMapper.Map<DataDictionaryEditDto>(dataDictionary);
            }

            return new GetDataDictionaryForEditOutput()
            {
                DataDictionary = dataDictionaryEditDto
            };
        }

        public async Task<ListResultDto<DataDictionaryListDto>> GetDataDictionaryListByTypeNames(GetDataDictionaryListByTypeNamesInput input)
        {
            var items = await _dataDictionaryRepository.GetAll()
                .WhereIf(input.TypeNames != null && input.TypeNames.Count() > 0, d => input.TypeNames.Contains(d.TypeName))
                .Include(d => d.DataDictionaryItem)
                .ToListAsync();

            return new ListResultDto<DataDictionaryListDto>(ObjectMapper.Map<List<DataDictionaryListDto>>(items));
        }

        public async Task CreateOrUpdateDataDictionary(CreateOrUpdateDataDictionaryInput input)
        {
            if (!input.DataDictionary.Id.HasValue)
            {
                await CreateDataDictionary(input);
            }
            else
            {
                await UpdateDataDictionary(input);
            }
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_Create)]
        private async Task CreateDataDictionary(CreateOrUpdateDataDictionaryInput input)
        {
            var existedDataDictionary = await _dataDictionaryRepository.GetAll().Where(d => d.TypeName == input.DataDictionary.TypeName).FirstOrDefaultAsync();

            if (existedDataDictionary != null)
            {
                throw new UserFriendlyException(L("该字典类型已存在，无法添加"));
            }

            var dataDictionary = ObjectMapper.Map<DataDictionary>(input.DataDictionary);
            await _dataDictionaryRepository.InsertAsync(dataDictionary);

            //模拟测试消息通知
            await _appNotifier.NewTaskAsync("字典类型已完成添加，可以开始使用了");
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_Update)]
        private async Task UpdateDataDictionary(CreateOrUpdateDataDictionaryInput input)
        {
            if (!input.DataDictionary.Id.HasValue || input.DataDictionary.Id.Value <= 0)
            {
                throw new UserFriendlyException(L("操作异常，数据有误"));
            }

            var dataDictionary = await _dataDictionaryRepository.GetAsync(input.DataDictionary.Id.Value);

            var existedDataDictionary = await _dataDictionaryRepository.GetAll().Where(d => d.TypeName == input.DataDictionary.TypeName).FirstOrDefaultAsync();
            if (existedDataDictionary != null && existedDataDictionary.Id != dataDictionary.Id)
            {
                throw new UserFriendlyException(L("该字典类型已存在，无法更新"));
            }

            ObjectMapper.Map(input.DataDictionary, dataDictionary);

            await _dataDictionaryRepository.UpdateAsync(dataDictionary);
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_Delete)]
        public async Task DeleteDataDictionary(List<EntityDto<long>> inputs)
        {
            foreach (var input in inputs)
            {
                await _dataDictionaryRepository.DeleteAsync(input.Id);
            }
        }
        #endregion

        #region 数据字典项
        public async Task<ListResultDto<DataDictionaryItemListDto>> GetAllDataDictionaryItem(GetAllDataDictionaryItemInput input)
        {
            var items = await _dataDictionaryItemRepository.GetAll()
                .Where(di => di.DataDictionaryId == input.DataDictionaryId)
                .ToListAsync();

            return new ListResultDto<DataDictionaryItemListDto>(items.Select(item =>
            {
                return ObjectMapper.Map<DataDictionaryItemListDto>(item);
            }).ToList());
        }

        public async Task<GetDataDictionaryItemForEditOutput> GetDataDictionaryItemForEdit(NullableIdDto<long> input)
        {
            var output = new GetDataDictionaryItemForEditOutput()
            {
                DataDictionaryItem = new DataDictionaryItemEditDto()
            };

            if (input.Id.HasValue)
            {
                var dataDictionaryItem = await _dataDictionaryItemRepository.GetAsync(input.Id.Value);
                output.DataDictionaryItem = ObjectMapper.Map<DataDictionaryItemEditDto>(dataDictionaryItem);
            }

            return output;
        }

        public async Task<GetDataDictionaryItemNameOutput> GetDataDictionaryItemName(GetDataDictionaryItemNameInput input)
        {
            var dataDictionary = await _dataDictionaryRepository.GetAll()
                .Where(d => d.TypeName == input.TypeName)
                .FirstOrDefaultAsync();

            if (dataDictionary == null)
            {
                throw new UserFriendlyException(string.Format("指定字典类型不存在:{0}", input.TypeName));
            }

            var dataDictionaryItem = await _dataDictionaryItemRepository.GetAll()
                .Where(di => di.DataDictionaryId == dataDictionary.Id && di.Code == input.ItemCode)
                .FirstOrDefaultAsync();

            return new GetDataDictionaryItemNameOutput()
            {
                ItemName = dataDictionaryItem == null ? "" : dataDictionaryItem.Name
            };
        }

        public async Task CreateOrUpdateDataDictionaryItem(CreateOrUpdateDataDictionaryItemInput input)
        {
            if (!input.DataDictionaryItem.Id.HasValue)
            {
                await CreateDataDictionaryItem(input);
            }
            else
            {
                await UpdateDataDictionaryItem(input);
            }
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_DataDictionaryItem_Create)]
        private async Task CreateDataDictionaryItem(CreateOrUpdateDataDictionaryItemInput input)
        {
            var existedDataDictionaryItem = await _dataDictionaryItemRepository.GetAll()
                .Where(d => d.DataDictionaryId == input.DataDictionaryItem.DataDictionaryId)
                .Where(d => d.Name == input.DataDictionaryItem.Name).FirstOrDefaultAsync();

            if (existedDataDictionaryItem != null)
            {
                throw new UserFriendlyException(L("该字典名称已存在，无法添加"));
            }

            var dataDictionaryItem = ObjectMapper.Map<DataDictionaryItem>(input.DataDictionaryItem);

            await _dataDictionaryItemRepository.InsertAsync(dataDictionaryItem);
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_DataDictionaryItem_Update)]
        private async Task UpdateDataDictionaryItem(CreateOrUpdateDataDictionaryItemInput input)
        {
            if (!input.DataDictionaryItem.Id.HasValue || input.DataDictionaryItem.Id.Value <= 0)
            {
                throw new UserFriendlyException(L("操作异常，数据有误"));
            }

            var dataDictionaryItem = await _dataDictionaryItemRepository.GetAsync(input.DataDictionaryItem.Id.Value);

            var isExistedDataDictionaryItem = await _dataDictionaryItemRepository.GetAll().Where(d => d.DataDictionaryId == dataDictionaryItem.DataDictionaryId && d.Name == input.DataDictionaryItem.Name && d.Id != dataDictionaryItem.Id).AnyAsync();
            if (isExistedDataDictionaryItem)
            {
                throw new UserFriendlyException(L("该字典名称已存在，无法更新"));
            }

            ObjectMapper.Map(input.DataDictionaryItem, dataDictionaryItem);

            await _dataDictionaryItemRepository.UpdateAsync(dataDictionaryItem);
        }

        [AbpAuthorize(PermissionNames.Pages_Base_DataDictionary_DataDictionaryItem_Delete)]
        public async Task DeleteDataDictionaryItem(List<EntityDto<long>> inputs)
        {
            foreach (var input in inputs)
            {
                await _dataDictionaryItemRepository.DeleteAsync(input.Id);
            }
        }
        #endregion   
    }
}
